package ch.so.sogis.interlis.checks;

import ch.so.sogis.interlis.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.util.Date;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import com.vividsolutions.jts.geom.*;
import com.vividsolutions.jts.util.*;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.index.quadtree.Quadtree;
import com.vividsolutions.jts.index.strtree.STRtree;
import com.vividsolutions.jump.feature.AttributeType;
import com.vividsolutions.jump.feature.BasicFeature;
import com.vividsolutions.jump.feature.FeatureDataset;
import com.vividsolutions.jump.feature.FeatureSchema;
import com.vividsolutions.jump.io.*;

import ch.interlis.iom.*;
import ch.interlis.iox.*;
import ch.interlis.iox_j.jts.Iox2jts;
import ch.interlis.iox_j.jts.Iox2jtsException;


public class Check_Strassenachsen {
	private Connection dbcon = null;
	private Statement stmt = null;
	
	private FeatureSchema fs_axis = null;
	private FeatureDataset fd_axis = null;
	
	private FeatureSchema fs_line = null;
	private FeatureDataset fd_res = null;
	
	private ResultSet rs = null;
	
	private String milli = new String().valueOf(new Date().getTime());
	private Boolean export_results = false;
	//private CoordinateList coords = new CoordinateList();
	
	
	public Check_Strassenachsen(Connection dbcon) {
		try {
			this.dbcon = dbcon;
			this.stmt = dbcon.createStatement();
		} catch(SQLException ex) {
			System.out.println("SQLEx");
			System.err.println("SQLException : " + ex.getMessage());
			}
		
		this.init();
	}
	
	private void init() {
		try {
			
			fs_axis = new FeatureSchema();
			fs_axis.addAttribute("tid", AttributeType.STRING);
			fs_axis.addAttribute("Strassenstueck_von", AttributeType.STRING);
			fs_axis.addAttribute("Text", AttributeType.STRING);
			fs_axis.addAttribute("Anfangspunkt", AttributeType.STRING);
			fs_axis.addAttribute("Geometrie", AttributeType.STRING);
			fd_axis = new FeatureDataset(fs_axis);
			
			fs_line = new FeatureSchema();
			fs_line.addAttribute("id", AttributeType.INTEGER);
			fs_line.addAttribute("error", AttributeType.INTEGER);
			fs_line.addAttribute("comment", AttributeType.STRING);
			fs_line.addAttribute("geometry", AttributeType.GEOMETRY);
			
			fd_res = new FeatureDataset(fs_line);
			
		
			rs = stmt.executeQuery("SELECT a.obje as tid, a.Strassenstueck_von, c.Text, a.Geometrie, a.Anfangspunkt FROM Gebaeudeadressen_Strassenstueck as a, Gebaeudeadressen_Lokalisation as b, Gebaeudeadressen_LokalisationsName as c " +
					"WHERE a.Strassenstueck_von = b.obje " +
					"AND c.Benannte = b.obje");
			
			while (rs.next()) {
				BasicFeature feat = new BasicFeature(fs_axis);
				feat.setAttribute("tid", rs.getString("tid"));
				feat.setAttribute("Strassenstueck_von", rs.getString("Strassenstueck_von"));
				feat.setAttribute("Text", rs.getString("Text"));
				feat.setAttribute("Anfangspunkt", rs.getString("Anfangspunkt"));
				feat.setAttribute("Geometrie", rs.getString("Geometrie"));				
				fd_axis.add(feat);
				//System.out.println(feat.getAttribute("Text"));
			}
			
			//System.out.println(fd_axis.size());
		
		} catch(SQLException ex) {
			System.out.println("SQLEx");
			System.err.println("SQLException : " + ex.getMessage());
		}
	}
	
	// Was soll zZ alles gepr?ft werden:
	// - doppelte Geometrien
	// - Kreisb?gen vorhanden?
	// - Anfangspunkt auf Start- oder Endpunkt?
	
	
	public void check() {
		
		ArrayList lines = new ArrayList();
		ArrayList segments = new ArrayList();
		
		//Quadtree quadSegments = new Quadtree();
		STRtree quadSegments = new STRtree();
		
		Iterator it = fd_axis.iterator();
		while(it.hasNext()) {
			BasicFeature axis_feat = (BasicFeature) it.next();
			String wkt_line = axis_feat.getString("Geometrie");
			String wkt_point = axis_feat.getString("Anfangspunkt");
			try {				
				// Strassenachse erstellen
				IomObject lineObj = Wkt2iox.wkt2polyline(wkt_line);
				CoordinateList coords = Iox2jts.polyline2JTS(lineObj, false, 3);
				Geometry line = new GeometryFactory().createLineString(coords.toCoordinateArray());	
				BasicFeature featLine = new BasicFeature(fs_line);
				featLine.setAttribute("id", featLine.getID());
				featLine.setGeometry(line);
				
				// Auf Kreisb�gen pr�fen
				if(wkt_line.indexOf("CIRCULARSTRING") > 1) {
					BasicFeature featArc = new BasicFeature(fs_line);
					featArc.setAttribute("id", featArc.getID());
					featArc.setAttribute("error", 1);
					featArc.setAttribute("comment", "Kreisbogen");
					featArc.setGeometry(line);
					fd_res.add(featArc);					
				}	
				
				// Anfangspunkt erstellen
				IomObject pointObj = Wkt2iox.wkt2point(wkt_point);
				Coordinate coord = Iox2jts.coord2JTS(pointObj);
				Geometry point = new GeometryFactory().createPoint(coord);
				
				// Pr�fen ob Interlis-Anfangspunkt weder mit Start- noch Endpunkt 
				// des Achsenabschnittes identisch ist.
				if(!point.equals(((LineString) line).getStartPoint()) && !point.equals(((LineString) line).getEndPoint())) {
					BasicFeature featAxis = new BasicFeature(fs_line);
					featAxis.setAttribute("id", featAxis.getID());
					featAxis.setAttribute("error", 2);
					featAxis.setAttribute("comment", point.toString());
					featAxis.setGeometry(line);
					fd_res.add(featAxis);
					
				}
				
				// einzelne Liniensegmente erstellen
				for(int i=1; i<coords.size(); i++) {
					Coordinate coord1 = coords.getCoordinate(i-1);
					Coordinate coord2 = coords.getCoordinate(i);
					Coordinate[] coordinates = new Coordinate[] {coord1, coord2};
					Geometry segment = new GeometryFactory().createLineString(coordinates);
					
					BasicFeature featSegment = new BasicFeature(fs_line);
					featSegment.setAttribute("id", featSegment.getID());
					featSegment.setGeometry(segment);			
					segments.add(featSegment);
					
					quadSegments.insert(segment.getEnvelopeInternal(), featSegment);
					
				}	

			} catch (ParseException e) {
				e.printStackTrace();
			} catch (Iox2jtsException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		Iterator jt = segments.iterator();
		while(jt.hasNext()) {
			BasicFeature feat_ref = (BasicFeature) jt.next();
			List queryList = quadSegments.query(feat_ref.getGeometry().getEnvelopeInternal());
			//System.out.println(queryList.size());
			Iterator kt = queryList.iterator();
		
			while(kt.hasNext()) {
				BasicFeature feat_tmp = ((BasicFeature) kt.next());
				if(feat_ref.getID() != feat_tmp.getID()) {
					Geometry line_inter = feat_ref.getGeometry().intersection(feat_tmp.getGeometry());
					if(line_inter instanceof LineString) {
						BasicFeature feat_inter = new BasicFeature(fs_line);
						feat_inter.setAttribute("id", feat_inter.getID());
						feat_inter.setAttribute("error", 3);
						feat_inter.setAttribute("comment", "doppelte Geometrie");
						feat_inter.setGeometry(line_inter);
						fd_res.add(feat_inter);
					}
				}
			}
		}

		//System.out.println(fd_res.size());
		
		if(export_results) {
			if(fd_res.size() > 0) {
				try {
			        DriverProperties dp_out = new DriverProperties("/home/bjsvwzie/geoprojekte/interlis/"+milli+"_check_strassenachsen.shp");
			        ShapefileWriter shp_out = new ShapefileWriter();
			        shp_out.write(fd_res, dp_out);    
				} catch (Exception ex) {
		            ex.printStackTrace();
		            System.err.println(ex.getMessage());                    
		        }		
			}
		}
	}
}
